use crate::{
    core::{error::AppError, policy::PolicyManager},
    utils::{cgroups, namespaces, seccomp},
};
use std::{
    collections::HashMap,
    ffi::CString,
    os::unix::prelude::{CommandExt, ExitStatusExt},
    path::{Path, PathBuf},
    process::{Command, ExitStatus},
};
use nix::{
    sched::{unshare, CloneFlags},
    sys::wait::waitpid,
    unistd::{execv, fork, ForkResult, Pid},
};

/// 沙盒配置参数
#[derive(Debug, Clone)]
pub struct SandboxConfig {
    pub read_only_paths: Vec<PathBuf>,
    pub writable_paths: Vec<PathBuf>,
    pub exposed_devices: Vec<String>,
    pub network_access: bool,
    pub cgroup_limits: cgroups::ResourceLimits,
    pub seccomp_profile: seccomp::Profile,
}

/// 沙盒执行器
pub struct SandboxExecutor {
    policy_mgr: PolicyManager,
    config: SandboxConfig,
}

impl SandboxExecutor {
    pub fn new(policy_mgr: PolicyManager, config: SandboxConfig) -> Self {
        Self { policy_mgr, config }
    }

    /// 安全执行沙盒化命令
    pub async fn execute(&self, cmd: &str, args: &[&str]) -> Result<ExitStatus, AppError> {
        // 1. 验证沙盒权限
        self.policy_mgr
            .check_authorization(
                "org.deepin.linglong.sandbox-execute",
                AuthInteraction::AllowUserInteraction,
            )
            .await?;

        // 2. 准备沙盒环境
        let temp_root = self.prepare_rootfs()?;
        let cgroup_dir = cgroups::create_scope(&self.config.cgroup_limits)?;

        // 3. 创建子进程
        match unsafe { fork() }? {
            ForkResult::Parent { child } => self.parent_process(child, cgroup_dir).await,
            ForkResult::Child => self.child_process(cmd, args, &temp_root)?,
        }
    }

    /// 准备容器根文件系统
    fn prepare_rootfs(&self) -> Result<PathBuf, AppError> {
        let temp_dir = tempfile::tempdir()?.into_path();
        
        // 创建 overlayfs
        namespaces::create_overlay(
            &self.config.read_only_paths,
            &self.config.writable_paths,
            &temp_dir,
        )?;

        // 创建设备节点
        for dev in &self.config.exposed_devices {
            namespaces::expose_device(&temp_dir, dev)?;
        }

        Ok(temp_dir)
    }

    /// 子进程执行逻辑
    fn child_process(&self, cmd: &str, args: &[&str], rootfs: &Path) -> Result<!, AppError> {
        // 1. 解除共享命名空间
        unshare(
            CloneFlags::CLONE_NEWNS |
            CloneFlags::CLONE_NEWPID |
            CloneFlags::CLONE_NEWNET |
            CloneFlags::CLONE_NEWUTS,
        )?;

        // 2. 挂载根文件系统
        namespaces::pivot_root(rootfs)?;

        // 3. 加载 seccomp 策略
        seccomp::load_profile(&self.config.seccomp_profile)?;

        // 4. 执行目标命令
        let c_cmd = CString::new(cmd)?;
        let c_args: Vec<CString> = args
            .iter()
            .map(|a| CString::new(*a))
            .collect::<Result<_, _>>()?;
        
        execv(&c_cmd, &c_args)?;
        unreachable!()
    }

    /// 父进程控制逻辑
    async fn parent_process(&self, child: Pid, cgroup_dir: PathBuf) -> Result<ExitStatus, AppError> {
        // 将进程加入 cgroup
        cgroups::add_task(cgroup_dir, child)?;

        // 等待子进程结束
        let status = waitpid(child, None)?;
        Ok(ExitStatus::from_raw(status.into()))
    }
}

/// 沙盒构建器（链式API）
pub struct SandboxBuilder {
    config: SandboxConfig,
    env_vars: HashMap<String, String>,
    policy_mgr: Option<PolicyManager>,
}

impl SandboxBuilder {
    pub fn new() -> Self {
        Self {
            config: SandboxConfig {
                read_only_paths: vec!["/usr".into(), "/lib".into(), "/lib64".into()],
                writable_paths: vec!["/tmp".into(), "/run/user".into()],
                exposed_devices: vec!["/dev/null".into(), "/dev/zero".into()],
                network_access: false,
                cgroup_limits: cgroups::ResourceLimits::default(),
                seccomp_profile: seccomp::Profile::default(),
            },
            env_vars: HashMap::new(),
            policy_mgr: None,
        }
    }

    /// 设置只读路径
    pub fn read_only_path(mut self, path: impl AsRef<Path>) -> Self {
        self.config.read_only_paths.push(path.as_ref().into());
        self
    }

    /// 设置可写路径
    pub fn writable_path(mut self, path: impl AsRef<Path>) -> Self {
        self.config.writable_paths.push(path.as_ref().into());
        self
    }

    /// 允许网络访问
    pub fn enable_network(mut self) -> Self {
        self.config.network_access = true;
        self
    }

    /// 设置CPU限制
    pub fn cpu_quota(mut self, cores: f64) -> Self {
        self.config.cgroup_limits.cpu_cores = cores;
        self
    }

    /// 设置内存限制
    pub fn memory_limit(mut self, mb: u64) -> Self {
        self.config.cgroup_limits.memory_limit_mb = mb;
        self
    }

    /// 附加策略管理器
    pub fn policy_manager(mut self, mgr: PolicyManager) -> Self {
        self.policy_mgr = Some(mgr);
        self
    }

    /// 构建沙盒执行器
    pub fn build(self) -> Result<SandboxExecutor, AppError> {
        Ok(SandboxExecutor {
            policy_mgr: self.policy_mgr.ok_or(AppError::ConfigError("缺失策略管理器".into()))?,
            config: self.config,
        })
    }
}

/// 沙盒运行时统计信息
#[derive(Debug)]
pub struct SandboxStats {
    pub cpu_usage: f64,
    pub memory_usage: u64,
    pub network_io: (u64, u64),
}

/// 沙盒监控器
pub struct SandboxMonitor {
    cgroup_dir: PathBuf,
}

impl SandboxMonitor {
    pub fn new(executor: &SandboxExecutor) -> Result<Self, AppError> {
        Ok(Self {
            cgroup_dir: cgroups::get_scope_path()?,
        })
    }

    /// 获取实时资源使用统计
    pub fn collect_stats(&self) -> Result<SandboxStats, AppError> {
        Ok(SandboxStats {
            cpu_usage: cgroups::read_cpu_usage(&self.cgroup_dir)?,
            memory_usage: cgroups::read_memory_usage(&self.cgroup_dir)?,
            network_io: namespaces::get_network_stats()?,
        })
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::core::policy::PolicyManager;

    #[tokio::test]
    async fn test_sandbox_execution() {
        let policy_mgr = PolicyManager::new().await.unwrap();
        let builder = SandboxBuilder::new()
            .cpu_quota(0.5)
            .memory_limit(512)
            .policy_manager(policy_mgr);

        let executor = builder.build().unwrap();
        let status = executor.execute("ls", &["-l"]).await.unwrap();
        assert!(status.success());
    }
}